home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n05 / dflt11.exe / WINDOW.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-29  |  15.5 KB  |  520 lines

  1. /* ---------- window.c ------------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. WINDOW inFocus = NULL;
  6.  
  7. int foreground, background;   /* current video colors */
  8.  
  9. static void TopLine(WINDOW, int, RECT);
  10.  
  11. /* --------- create a window ------------ */
  12. WINDOW CreateWindow(
  13.     CLASS class,              /* class of this window       */
  14.     char *ttl,                /* title or NULL              */
  15.     int left, int top,        /* upper left coordinates     */
  16.     int height, int width,    /* dimensions                 */
  17.     void *extension,          /* pointer to additional data */
  18.     WINDOW parent,            /* parent of this window      */
  19.     int (*wndproc)(struct window *,enum messages,PARAM,PARAM),
  20.     int attrib)               /* window attribute           */
  21. {
  22.     WINDOW wnd = calloc(1, sizeof(struct window));
  23.     get_videomode();
  24.     if (wnd != NULL)    {
  25.         int base;
  26.         /* ----- height, width = -1: fill the screen ------- */
  27.         if (height == -1)
  28.             height = SCREENHEIGHT;
  29.         if (width == -1)
  30.             width = SCREENWIDTH;
  31.         /* ----- coordinates -1, -1 = center the window ---- */
  32.         if (left == -1)
  33.             wnd->rc.lf = (SCREENWIDTH-width)/2;
  34.         else
  35.             wnd->rc.lf = left;
  36.         if (top == -1)
  37.             wnd->rc.tp = (SCREENHEIGHT-height)/2;
  38.         else
  39.             wnd->rc.tp = top;
  40.         wnd->attrib = attrib;
  41.         if (ttl != NULL)
  42.             AddAttribute(wnd, HASTITLEBAR);
  43.         if (wndproc == NULL)
  44.             wnd->wndproc = classdefs[class].wndproc;
  45.         else
  46.             wnd->wndproc = wndproc;
  47.         /* ---- derive attributes of base classes ---- */
  48.         base = class;
  49.         while (base != -1)    {
  50.             AddAttribute(wnd, classdefs[base].attrib);
  51.             base = classdefs[base].base;
  52.         }
  53.         if (parent && !TestAttribute(wnd, NOCLIP))    {
  54.             /* -- keep upper left within borders of parent - */
  55.             wnd->rc.lf = max(wnd->rc.lf,GetClientLeft(parent));
  56.             wnd->rc.tp = max(wnd->rc.tp,GetClientTop(parent));
  57.         }
  58.         wnd->class = class;
  59.         wnd->extension = extension;
  60.         wnd->rc.rt = GetLeft(wnd)+width-1;
  61.         wnd->rc.bt = GetTop(wnd)+height-1;
  62.         wnd->ht = height;
  63.         wnd->wd = width;
  64.         if (ttl != NULL)
  65.             InsertTitle(wnd, ttl);
  66.         wnd->nextfocus = wnd->prevfocus = wnd->dFocus = NULL;
  67.         wnd->parent = parent;
  68.         wnd->oldcondition = wnd->condition = ISRESTORED;
  69.         wnd->RestoredRC = wnd->rc;
  70.         wnd->PrevKeyboard = wnd->PrevMouse = NULL;
  71.         SendMessage(wnd, CREATE_WINDOW, 0, 0);
  72.         InitWindowColors(wnd);
  73.         if (isVisible(wnd))
  74.             SendMessage(wnd, SHOW_WINDOW, 0, 0);
  75.     }
  76.     return wnd;
  77. }
  78.  
  79. /* -------- add a title to a window --------- */
  80. void AddTitle(WINDOW wnd, char *ttl)
  81. {
  82.     InsertTitle(wnd, ttl);
  83.     SendMessage(wnd, BORDER, 0, 0);
  84. }
  85.  
  86. /* ----- insert a title into a window ---------- */
  87. void InsertTitle(WINDOW wnd, char *ttl)
  88. {
  89.     if ((wnd->title=realloc(wnd->title,strlen(ttl)+1)) != NULL)
  90.         strcpy(wnd->title, ttl);
  91. }
  92.  
  93. static unsigned char line[300];
  94.  
  95. /* ------ write a line to video window client area ------ */
  96. void writeline(WINDOW wnd, char *str, int x, int y, BOOL pad)
  97. {
  98.     char *cp;
  99.     int len;
  100.     int dif;
  101.     char wline[200];
  102.  
  103.     memset(wline, 0, 200);
  104.     len = LineLength(str);
  105.     dif = strlen(str) - len;
  106.     strncpy(wline, str, ClientWidth(wnd) + dif);
  107.     if (pad)    {
  108.         cp = wline+strlen(wline);
  109.         while (len++ < ClientWidth(wnd)-x)
  110.             *cp++ = ' ';
  111.     }
  112.     wputs(wnd, wline, x, y);
  113. }
  114.  
  115. RECT AdjustRectangle(WINDOW wnd, RECT rc)
  116. {
  117.     /* -------- adjust the rectangle ------- */
  118.     if (TestAttribute(wnd, HASBORDER))    {
  119.         if (RectLeft(rc) == 0)
  120.             --rc.rt;
  121.         else if (RectLeft(rc) < RectRight(rc) &&
  122.                 RectLeft(rc) < WindowWidth(wnd)+1)
  123.             --rc.lf;
  124.     }
  125.     if (TestAttribute(wnd, HASBORDER | HASTITLEBAR))    {
  126.         if (RectTop(rc) == 0)
  127.             --rc.bt;
  128.         else if (RectTop(rc) < RectBottom(rc) &&
  129.                 RectTop(rc) < WindowHeight(wnd)+1)
  130.             --rc.tp;
  131.     }
  132.     RectRight(rc) = max(RectLeft(rc),
  133.                         min(RectRight(rc),WindowWidth(wnd)));
  134.     RectBottom(rc) = max(RectTop(rc),
  135.                         min(RectBottom(rc),WindowHeight(wnd)));
  136.     return rc;
  137. }
  138.  
  139. /* -------- display a window's title --------- */
  140. void DisplayTitle(WINDOW wnd, RECT *rcc)
  141. {
  142.     if (GetTitle(wnd) != NULL)    {
  143.         int tlen = min(strlen(GetTitle(wnd)), WindowWidth(wnd)-2);
  144.         int tend = WindowWidth(wnd)-3-BorderAdj(wnd);
  145.         RECT rc;
  146.  
  147.         if (rcc == NULL)
  148.             rc = RelativeWindowRect(wnd, WindowRect(wnd));
  149.         else
  150.             rc = *rcc;
  151.         rc = AdjustRectangle(wnd, rc);
  152.  
  153.         if (SendMessage(wnd, TITLE, (PARAM) rcc, 0))    {
  154.             if (wnd == inFocus)    {
  155.                 foreground = cfg.clr[TITLEBAR] [HILITE_COLOR] [FG];
  156.                 background = cfg.clr[TITLEBAR] [HILITE_COLOR] [BG];
  157.             }
  158.             else    {
  159.                 foreground = cfg.clr[TITLEBAR] [STD_COLOR] [FG];
  160.                 background = cfg.clr[TITLEBAR] [STD_COLOR] [BG];
  161.             }
  162.             memset(line,' ',WindowWidth(wnd));
  163. #ifdef INCLUDE_MINIMIZE
  164.             if (wnd->condition != ISMINIMIZED)
  165. #endif
  166.                 strncpy(line + ((WindowWidth(wnd)-2 - tlen) / 2),
  167.                     wnd->title, tlen);
  168.             if (TestAttribute(wnd, CONTROLBOX))
  169.                 line[2-BorderAdj(wnd)] = CONTROLBOXCHAR;
  170.             if (TestAttribute(wnd, MINMAXBOX))    {
  171.                 switch (wnd->condition)    {
  172.                     case ISRESTORED:
  173. #ifdef INCLUDE_MAXIMIZE
  174.                         line[tend+1] = MAXPOINTER;
  175. #endif
  176. #ifdef INCLUDE_MINIMIZE
  177.                         line[tend]   = MINPOINTER;
  178. #endif
  179.                         break;
  180. #ifdef INCLUDE_MINIMIZE
  181.                     case ISMINIMIZED:
  182.                         line[tend+1] = MAXPOINTER;
  183.                         break;
  184. #endif
  185. #ifdef INCLUDE_MAXIMIZE
  186.                     case ISMAXIMIZED:
  187. #ifdef INCLUDE_MINIMIZE
  188.                         line[tend]   = MINPOINTER;
  189. #endif
  190. #ifdef INCLUDE_RESTORE
  191.                         line[tend+1] = RESTOREPOINTER;
  192. #endif
  193.                         break;
  194. #endif
  195.                     default:
  196.                         break;
  197.                 }
  198.             }
  199.             line[RectRight(rc)+1] = line[tend+3] = '\0';
  200.             writeline(wnd, line+RectLeft(rc),
  201.                            RectLeft(rc)+BorderAdj(wnd),
  202.                            0,
  203.                            FALSE);
  204.         }
  205.     }
  206. }
  207.  
  208. /* --- display right border shadow character of a window --- */
  209. static void near shadow_char(WINDOW wnd, int y)
  210. {
  211.     int fg = foreground;
  212.     int bg = background;
  213.     int x = WindowWidth(wnd);
  214.     int c = videochar(GetLeft(wnd)+x, GetTop(wnd)+y);
  215.  
  216.     if (TestAttribute(wnd, SHADOW) == 0 || cfg.mono)
  217.         return;
  218.     foreground = LIGHTGRAY;
  219.     background = BLACK;
  220.     wputch(wnd, c, x, y);
  221.     foreground = fg;
  222.     background = bg;
  223. }
  224.  
  225. /* --- display the bottom border shadow line for a window -- */
  226. static void near shadowline(WINDOW wnd, RECT rc)
  227. {
  228.     int i;
  229.     int y = GetBottom(wnd)+1;
  230.     int fg = foreground;
  231.     int bg = background;
  232.  
  233.     if ((TestAttribute(wnd, SHADOW)) == 0 || cfg.mono)
  234.         return;
  235.     for (i = 0; i < WindowWidth(wnd)+1; i++)
  236.         line[i] = videochar(GetLeft(wnd)+i, y);
  237.     line[i] = '\0';
  238.     foreground = LIGHTGRAY;
  239.     background = BLACK;
  240.     line[RectRight(rc)+1] = '\0';
  241.     if (RectLeft(rc) == 0)
  242.         rc.lf++;
  243.     ClipString++;
  244.     wputs(wnd, line+RectLeft(rc), RectLeft(rc),
  245.         WindowHeight(wnd));
  246.     --ClipString;
  247.     foreground = fg;
  248.     background = bg;
  249. }
  250.  
  251. /* ------- display a window's border ----- */
  252. void RepaintBorder(WINDOW wnd, RECT *rcc)
  253. {
  254.     int y;
  255.     unsigned int lin, side, ne, nw, se, sw;
  256.     RECT rc, clrc;
  257.  
  258.     if (!TestAttribute(wnd, HASBORDER))
  259.         return;
  260.     if (rcc == NULL)    {
  261.         rc = RelativeWindowRect(wnd, WindowRect(wnd));
  262.         if (TestAttribute(wnd, SHADOW) || cfg.mono == 0)    {
  263.             rc.rt++;
  264.             rc.bt++;
  265.         }
  266.     }
  267.     else
  268.         rc = *rcc;
  269.     clrc = AdjustRectangle(wnd, rc);
  270.  
  271.     if (wnd == inFocus)    {
  272.         lin  = FOCUS_LINE;
  273.         side = FOCUS_SIDE;
  274.         ne   = FOCUS_NE;
  275.         nw   = FOCUS_NW;
  276.         se   = FOCUS_SE;
  277.         sw   = FOCUS_SW;
  278.     }
  279.     else    {
  280.         lin  = LINE;
  281.         side = SIDE;
  282.         ne   = NE;
  283.         nw   = NW;
  284.         se   = SE;
  285.         sw   = SW;
  286.     }
  287.     line[WindowWidth(wnd)] = '\0';
  288.     /* ---------- window title ------------ */
  289.     if (TestAttribute(wnd, HASTITLEBAR))
  290.         if (RectTop(rc) == 0)
  291.             if (RectLeft(rc) < WindowWidth(wnd)-BorderAdj(wnd))
  292.                 DisplayTitle(wnd, &rc);
  293.     foreground = FrameForeground(wnd);
  294.     background = FrameBackground(wnd);
  295.     /* -------- top frame corners --------- */
  296.     if (RectTop(rc) == 0)    {
  297.         if (RectLeft(rc) == 0)
  298.             wputch(wnd, nw, 0, 0);
  299.         if (RectLeft(rc) < WindowWidth(wnd))    {
  300.             if (RectRight(rc) >= WindowWidth(wnd)-1)
  301.                 wputch(wnd, ne, WindowWidth(wnd)-1, 0);
  302.             TopLine(wnd, lin, clrc);
  303.         }
  304.     }
  305.  
  306.     /* ----------- window body ------------ */
  307.     for (y = RectTop(rc); y <= RectBottom(rc); y++)    {
  308.         int ch;
  309.         if (y == 0 || y >= WindowHeight(wnd)-1)
  310.             continue;
  311.         if (RectLeft(rc) == 0)
  312.             wputch(wnd, side, 0, y);
  313.         if (RectLeft(rc) < WindowWidth(wnd) &&
  314.                 RectRight(rc) >= WindowWidth(wnd)-1)    {
  315.             if (TestAttribute(wnd, VSCROLLBAR))
  316.                 ch = (    y == 1 ? UPSCROLLBOX      :
  317.                           y == WindowHeight(wnd)-2  ?
  318.                                 DOWNSCROLLBOX       :
  319.                           y-1 == wnd->VScrollBox    ?
  320.                                 SCROLLBOXCHAR       :
  321.                           SCROLLBARCHAR );
  322.             else
  323.                 ch = side;
  324.             wputch(wnd, ch, WindowWidth(wnd)-1, y);
  325.         }
  326.         if (RectRight(rc) == WindowWidth(wnd))
  327.             shadow_char(wnd, y);
  328.     }
  329.  
  330.     if (RectTop(rc) <= WindowHeight(wnd)-1 &&
  331.             RectBottom(rc) >= WindowHeight(wnd)-1)    {
  332.         /* -------- bottom frame corners ---------- */
  333.         if (RectLeft(rc) == 0)
  334.             wputch(wnd, sw, 0, WindowHeight(wnd)-1);
  335.         if (RectLeft(rc) < WindowWidth(wnd) &&
  336.                 RectRight(rc) >= WindowWidth(wnd)-1)
  337.             wputch(wnd, se, WindowWidth(wnd)-1,
  338.                 WindowHeight(wnd)-1);
  339.  
  340.  
  341.         if (wnd->StatusBar == NULL)    {
  342.             /* ----------- bottom line ------------- */
  343.             memset(line,lin,WindowWidth(wnd)-1);
  344.             if (TestAttribute(wnd, HSCROLLBAR))    {
  345.                 line[0] = LEFTSCROLLBOX;
  346.                 line[WindowWidth(wnd)-3] = RIGHTSCROLLBOX;
  347.                 memset(line+1, SCROLLBARCHAR, WindowWidth(wnd)-4);
  348.                 line[wnd->HScrollBox] = SCROLLBOXCHAR;
  349.             }
  350.             line[WindowWidth(wnd)-2] = line[RectRight(rc)] = '\0';
  351.             if (RectLeft(rc) != RectRight(rc) ||
  352.             (RectLeft(rc) && RectLeft(rc) < WindowWidth(wnd)-1))
  353.                 writeline(wnd,
  354.                     line+(RectLeft(clrc)),
  355.                     RectLeft(clrc)+1,
  356.                     WindowHeight(wnd)-1,
  357.                     FALSE);
  358.         }
  359.         if (RectRight(rc) == WindowWidth(wnd))
  360.             shadow_char(wnd, WindowHeight(wnd)-1);
  361.     }
  362.     if (RectBottom(rc) == WindowHeight(wnd))
  363.         /* ---------- bottom shadow ------------- */
  364.         shadowline(wnd, rc);
  365. }
  366.  
  367. static void TopLine(WINDOW wnd, int lin, RECT rc)
  368. {
  369.     if (TestAttribute(wnd, HASMENUBAR))
  370.         return;
  371.     if (TestAttribute(wnd, HASTITLEBAR) && GetTitle(wnd))
  372.         return;
  373.     if (RectLeft(rc) == 0)    {
  374.         RectLeft(rc) += BorderAdj(wnd);
  375.         RectRight(rc) += BorderAdj(wnd);
  376.     }
  377.     if (RectRight(rc) < WindowWidth(wnd)-1)
  378.         RectRight(rc)++;
  379.  
  380.     if (RectLeft(rc) < RectRight(rc))    {
  381.         /* ----------- top line ------------- */
  382.         memset(line,lin,WindowWidth(wnd)-1);
  383.         if (TestAttribute(wnd, CONTROLBOX))    {
  384.             strncpy(line+1, "   ", 3);
  385.             *(line+2) = CONTROLBOXCHAR;
  386.         }
  387.         line[RectRight(rc)] = '\0';
  388.         writeline(wnd, line+RectLeft(rc),
  389.             RectLeft(rc), 0, FALSE);
  390.     }
  391. }
  392.  
  393. /* ------ clear the data space of a window -------- */
  394. void ClearWindow(WINDOW wnd, RECT *rcc, int clrchar)
  395. {
  396.     if (isVisible(wnd))    {
  397.         int y;
  398.         RECT rc;
  399.  
  400.         if (rcc == NULL)
  401.             rc = RelativeWindowRect(wnd, WindowRect(wnd));
  402.         else
  403.             rc = *rcc;
  404.  
  405.         if (RectLeft(rc) == 0)
  406.             RectLeft(rc) = BorderAdj(wnd);
  407.         if (RectRight(rc) > WindowWidth(wnd)-1)
  408.             RectRight(rc) = WindowWidth(wnd)-1;
  409.         SetStandardColor(wnd);
  410.         memset(line, clrchar, sizeof line);
  411.         line[RectRight(rc)+1] = '\0';
  412.         for (y = RectTop(rc); y <= RectBottom(rc); y++)    {
  413.             if (y < TopBorderAdj(wnd) ||
  414.                     y > ClientHeight(wnd)+
  415.                         (TestAttribute(wnd, HASMENUBAR) ? 1 : 0))
  416.                 continue;
  417.             writeline(wnd,
  418.                 line+(RectLeft(rc)),
  419.                 RectLeft(rc),
  420.                 y,
  421.                 FALSE);
  422.         }
  423.     }
  424. }
  425.  
  426. /* -- adjust a window's rectangle to clip it to its parent - */
  427. static RECT near ClipRect(WINDOW wnd)
  428. {
  429.     RECT rc;
  430.     rc = WindowRect(wnd);
  431.     if (TestAttribute(wnd, SHADOW) || cfg.mono == 0)    {
  432.         RectBottom(rc)++;
  433.         RectRight(rc)++;
  434.     }
  435.     return ClipRectangle(wnd, rc);
  436. }
  437.  
  438. /* -- get the video memory that is to be used by a window -- */
  439. void GetVideoBuffer(WINDOW wnd)
  440. {
  441.     RECT rc;
  442.     int ht;
  443.     int wd;
  444.  
  445.     rc = ClipRect(wnd);
  446.     ht = RectBottom(rc) - RectTop(rc) + 1;
  447.     wd = RectRight(rc) - RectLeft(rc) + 1;
  448.     wnd->videosave = realloc(wnd->videosave, (ht * wd * 2));
  449.     get_videomode();
  450.     if (wnd->videosave != NULL)
  451.         getvideo(rc, wnd->videosave);
  452. }
  453.  
  454. /* --- restore the video memory that was used by a window -- */
  455. void RestoreVideoBuffer(WINDOW wnd)
  456. {
  457.     if (wnd->videosave != NULL)    {
  458.         RECT rc;
  459.         rc = ClipRect(wnd);
  460.         storevideo(rc, wnd->videosave);
  461.         free(wnd->videosave);
  462.         wnd->videosave = NULL;
  463.     }
  464. }
  465.  
  466. /* ------ compute the logical line length of a window ------ */
  467. int LineLength(char *ln)
  468. {
  469.     int len = strlen(ln);
  470.     char *cp = ln;
  471.     while ((cp = strchr(cp, CHANGECOLOR)) != NULL)    {
  472.         cp++;
  473.         len -= 3;
  474.     }
  475.     cp = ln;
  476.     while ((cp = strchr(cp, RESETCOLOR)) != NULL)    {
  477.         cp++;
  478.         --len;
  479.     }
  480.     return len;
  481. }
  482.  
  483. void InitWindowColors(WINDOW wnd)
  484. {
  485.     int fbg,col;
  486.     int cls = GetClass(wnd);
  487.     /* window classes without assigned colors inherit parent's colors */
  488.     if (cfg.clr[cls][0][0] == 0xff && GetParent(wnd) != NULL)
  489.         cls = GetClass(GetParent(wnd));
  490.     /* ---------- set the colors ---------- */
  491.     for (fbg = 0; fbg < 2; fbg++)
  492.         for (col = 0; col < 4; col++)
  493.             wnd->WindowColors[col][fbg] = cfg.clr[cls][col][fbg];
  494. }
  495.  
  496. void PutWindowChar(WINDOW wnd, int c, int x, int y)
  497. {
  498.     if (x < ClientWidth(wnd) && y < ClientHeight(wnd))
  499.         wputch(wnd, c, x+BorderAdj(wnd), y+TopBorderAdj(wnd));
  500. }
  501.  
  502. void PutWindowLine(WINDOW wnd, void *s, int x, int y)
  503. {
  504.     int saved = FALSE, sv;
  505.     if (x < ClientWidth(wnd) && y < ClientHeight(wnd))    {
  506.         char *en = (char *)s+ClientWidth(wnd)-x;
  507.         if (strlen(s)+x > ClientWidth(wnd))    {
  508.             sv = *en;
  509.             *en = '\0';
  510.             saved = TRUE;
  511.         }
  512.         ClipString++;
  513.         wputs(wnd, s, x+BorderAdj(wnd), y+TopBorderAdj(wnd));
  514.         --ClipString;
  515.         if (saved)
  516.             *en = sv;
  517.     }
  518. }
  519.  
  520.